package com.mall.seckill_mall.controller;

import com.mall.seckill_mall.annotations.AccessLimit;
import com.mall.seckill_mall.common.RedisPreffix;
import com.mall.seckill_mall.common.Result;
import com.mall.seckill_mall.entity.Goods;
import com.mall.seckill_mall.enums.CodeMessage;
import com.mall.seckill_mall.exception.GoodsException;
import com.mall.seckill_mall.rabbitmq.sender.MQProducer;
import com.mall.seckill_mall.service.GoodsService;
import com.mall.seckill_mall.utils.ResultUtil;
import com.mall.seckill_mall.vo.GoodsList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@RestController
@RequestMapping("/goods")
@Lazy(value = false)
public class GoodsController implements InitializingBean {

    private Logger logger = LoggerFactory.getLogger(GoodsController.class);

    private Map<String, Boolean> goodsOverMap = new ConcurrentHashMap<>();

    @Autowired
    private GoodsService goodsService;

    @Autowired
    private RedisTemplate<String, Serializable> redisTemplate;

    /**
     * 服务器启动时，初始化商品信息
     *  1. 商品列表 --> redis
     *  2. 商品售罄标记 --> map
     *  3. 商品静态信息 --> redis
     * @throws Exception 服务器错误
     */
    @Override
    public void afterPropertiesSet() throws Exception {
//        String listKey = RedisPreffix.GOODS_LIST_PREFFIX;
//        redisTemplate.delete(listKey);
        List<GoodsList> goodsLists = goodsService.selectOnlyUp();
        logger.debug("init goodsList: {}", goodsLists.toString());
        for(GoodsList goodsList : goodsLists) {
            String stockKey = RedisPreffix.STOCK_PREFFIX.concat(goodsList.getGoodsId());
            redisTemplate.opsForValue().set(stockKey, goodsList.getGoodsStock());
            String goodsId = goodsList.getGoodsId();
            goodsService.getGoods(goodsId);
            if(goodsList.getGoodsStock() <= 0) {
                goodsOverMap.put(goodsList.getGoodsId(), true);
            }
        }
        logger.debug("init goodsOverMap: {}", goodsOverMap.toString());
    }

    @AccessLimit(period = 10, maxCount = 5)
    @GetMapping("/{goodsId}")
    public Result getGoods(@PathVariable("goodsId") String goodsId) {
        Goods goods = goodsService.getGoods(goodsId);
        if(goods == null) {
            return ResultUtil.error(CodeMessage.GOODS_NOT_EXISTS);
        }
        return ResultUtil.success(goods);
    }

    @GetMapping("/list")
    public Result listGoods() {
        List<GoodsList> goodsLists = null;
        try {
            goodsLists = goodsService.selectOnlyUp();
        } catch (GoodsException e) {
            throw new GoodsException(CodeMessage.EMPTY_GOODS);
        }
        return ResultUtil.success(goodsLists);
    }

    @PostMapping("")
    public Result addGoods(@Valid Goods goods) {
        try {
            goodsService.createGoods(goods);
        } catch (GoodsException e) {
            throw e;
        }
        if(goods.getGoodsStock() > 0) {
            goodsOverMap.put(goods.getGoodsId(), true);
        } else {
            goodsOverMap.put(goods.getGoodsId(), false);
        }
        return ResultUtil.success();
    }

    @DeleteMapping("/{goodsId}")
    public Result deleteGoods(@PathVariable("goodsId") String goodsId) {
        goodsService.deleteGoods(goodsId);
        return ResultUtil.success();
    }

    @PutMapping("/{goodsId}")
    public Result updateGoods(@PathVariable("goodsId") String goodsId, Goods goods){
        goodsService.updateGoods(goods);
        return ResultUtil.success();
    }

    @GetMapping("/api")
    public Result testApi() {
        return ResultUtil.success();
    }

    @GetMapping("/status/{goodsId}")
    public Result getRemain(@PathVariable("goodsId") String goodsId) {
        return ResultUtil.success(goodsService.getSeckillStatus(goodsId));
    }
}
